package slxy.jiangtao.dts.core.common.hibernate.qbc;

import slxy.jiangtao.dts.core.util.ContextHolderUtils;
import org.hibernate.FetchMode;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.ProjectionList;

import javax.servlet.http.HttpServletRequest;
import java.util.HashSet;
import java.util.Set;

/** 拼装Hibernate条件 */
public class DetachedCriteriaUtil {

  /** 小写字母X */
  public static final String MIDDLE_SEPRATOR_CHAR = "x";
  /** 两个空格 */
  public static final String SEPARATOR_TWO_SPACE = "  "; // 两个空格，避免和"日期 时间"中的空格混淆
  /** 此字符串内容为" <= x <= "，不包括引号 */
  public static ProjectionList projectionList;

  public static ProjectionList getProjectionList() {
    return projectionList;
  }

  private DetachedCriteriaUtil() {
    //do not allow to create Object
  }

  /**
   * 自动拼装条件 2008-11-3
   *
   * @param pojoClazz 实体类名
   * @param startChar 参数统一的开始字符
   * @param alias 别名
   * @return DetachedCriteria 组装好的查询条件
   * @author 苍鹰
   */
  public static DetachedCriteria createDetachedCriteria(
      Class<?> pojoClazz, String startChar, String alias) {
    return createDetachedCriteria(pojoClazz, startChar, alias, null);
  }

  /**
   * 自动拼装条件 2008-11-3
   *
   * @param pojoClazz 实体类名
   * @param startChar 参数统一的开始字符
   * @param alias 别名
   * @param columnNames 作为select子句的属性名集合
   * @return DetachedCriteria 组装好的查询条件
   * @author 苍鹰
   */
  public static DetachedCriteria createDetachedCriteria(
      Class<?> pojoClazz, String startChar, String alias, String[] columnNames) {
    return createDetachedCriteria(pojoClazz, startChar, alias, columnNames, null);
  }

  /**
   * 自动拼装条件 2008-11-3
   *
   * @param pojoClazz 实体类名
   * @param startChar 参数统一的开始字符
   * @param columnNames 作为select子句的属性名集合
   * @param excludeParameters 不作为查询条件的参数
   * @param alias 别名
   * @return DetachedCriteria 组装好的查询条件
   * @author 苍鹰
   */
  public static DetachedCriteria createDetachedCriteria(
      Class<?> pojoClazz,
      String startChar,
      String alias,
      String[] columnNames,
      String[] excludeParameters) {
    DetachedCriteria criteria = DetachedCriteria.forClass(pojoClazz, alias);
    if (columnNames != null && columnNames.length > 0) {
      //selectColumn(criteria, columnNames, pojoClazz, false);
    }
    return criteria;
  }

  private static final String ALIAS_KEY_IN_REQUEST = "ALIAS_KEY_IN_REQUEST";
  private static final String HAS_JOIN_TABLE_KEY_IN_REQUEST = "HAS_JOIN_TABLE_KEY_IN_REQUEST";

  private static void setAliasToRequest(HttpServletRequest request, Set<String> aliases) {
    request.setAttribute(ALIAS_KEY_IN_REQUEST, aliases);
  }

  @SuppressWarnings("unchecked")
  private static Set<String> getAliasesFromRequest() {
    Set<String> aliases =
        (Set<String>) ContextHolderUtils.getRequest().getAttribute(ALIAS_KEY_IN_REQUEST);
    if (aliases == null) {
      aliases = new HashSet<String>(5);
      setAliasToRequest(ContextHolderUtils.getRequest(), aliases);
    }
    return aliases;
  }

  private static boolean getHasJoinTatleFromRequest() {
    Boolean hasJoin =
        (Boolean) ContextHolderUtils.getRequest().getAttribute(HAS_JOIN_TABLE_KEY_IN_REQUEST);
    return hasJoin == null ? false : hasJoin;
  }

  private static final String POINT = ".";

  /**
   * 创建别名
   *
   * @param criteria
   * @param rootAlais
   * @param aliases
   * @param columns
   * @param currentStep
   * @author 苍鹰 2009-9-9
   */
  private static void createAlias(
      DetachedCriteria criteria,
      String rootAlais,
      Set<String> aliases,
      String[] columns,
      int currentStep) {
    if (currentStep < columns.length - 1) {
      if (!aliases.contains(converArrayToAlias(columns, currentStep))) {
        if (currentStep > 0) {
          criteria
              .createAlias(
                  converArrayToAlias(columns, currentStep - 1) + POINT + columns[currentStep],
                  converArrayToAlias(columns, currentStep))
              .setFetchMode(columns[currentStep], FetchMode.JOIN);
        } else {
          criteria
              .createAlias(
                  rootAlais + POINT + columns[currentStep],
                  converArrayToAlias(columns, currentStep))
              .setFetchMode(columns[currentStep], FetchMode.JOIN);
        }
        aliases.add(converArrayToAlias(columns, currentStep));
      }
      currentStep++;
      createAlias(criteria, rootAlais, aliases, columns, currentStep);
    }
  }

  /**
   * 从"organization.parentOrganization.parentOrganization.parentOrganization.id" 得到
   * "organization_parentOrganization_parentOrganization_parentOrganization.id"
   *
   * @param property
   * @return
   * @author 苍鹰 2009-9-20
   */
  public static String getAliasFromPropertyChainString(String property) {
    if (property.contains(".")) {
      return property.substring(0, property.lastIndexOf(POINT)).replaceAll("\\.", "_")
          + property.substring(property.lastIndexOf(POINT));
    }
    return property;
  }

  /**
   * 从数组中创建ALIAS
   *
   * @param columns
   * @param currentStep
   * @return
   * @author 苍鹰 2009-9-10
   */
  private static String converArrayToAlias(String[] columns, int currentStep) {
    StringBuilder alias = new StringBuilder();
    for (int i = 0; i <= currentStep; i++) {
      if (alias.length() > 0) {
        alias.append("_");
      }
      alias.append(columns[i]);
    }
    return alias.toString();
  }
}
